package com.atguigu.tingshu.payment.service.impl;

import com.atguigu.tingshu.account.client.RechargeInfoFeignClient;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.account.RechargeInfo;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.order.client.OrderInfoFeignClient;
import com.atguigu.tingshu.payment.config.WxPayV3Config;
import com.atguigu.tingshu.payment.service.PaymentInfoService;
import com.atguigu.tingshu.payment.service.WxPayService;
import com.atguigu.tingshu.payment.util.PayUtil;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.payment.WeChatPayVo;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

	private final  PaymentInfoService paymentInfoService;

	private final  OrderInfoFeignClient orderInfoFeignClient ;

	private final  RSAAutoCertificateConfig rsaAutoCertificateConfig ;

	private final  WxPayV3Config wxPayV3Config ;

	private final  UserInfoFeignClient userInfoFeignClient ;

	private final  RechargeInfoFeignClient rechargeInfoFeignClient ;

	@Autowired
	public WxPayServiceImpl(PaymentInfoService paymentInfoService, OrderInfoFeignClient orderInfoFeignClient, RSAAutoCertificateConfig rsaAutoCertificateConfig, WxPayV3Config wxPayV3Config, UserInfoFeignClient userInfoFeignClient, RechargeInfoFeignClient rechargeInfoFeignClient) {
		this.paymentInfoService = paymentInfoService;
		this.orderInfoFeignClient = orderInfoFeignClient;
		this.rsaAutoCertificateConfig = rsaAutoCertificateConfig;
		this.wxPayV3Config = wxPayV3Config;
		this.userInfoFeignClient = userInfoFeignClient;
		this.rechargeInfoFeignClient = rechargeInfoFeignClient;
	}

	/**
	 * @description: 当选择微信下单时 会调用此接口
	 * @author Petrichor
	 * @date 2024/1/9 23:18
	 * @param paymentType "支付类型：1301-订单 1302-充值"
	 * @param orderNo 订单号
	 * @return WeChatPayVo 请求微信JSAPI下单接口响应数据模型
	 **/
	@Override
	public WeChatPayVo createJsapi(String paymentType, String orderNo) {

		try {
			// 定义一个变量
			String description = "";

			// 订单支付逻辑
			if (SystemConstant.PAYMENT_TYPE_ORDER.equals(paymentType)) {

				log.info("订单支付，请求微信支付平台支付下单接口...");

				// 根据订单的编号查询订单数据，判断订单的状态是否为  "已取消" , 如果是"已取消"无需执行后续操作
				Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderNo);
				OrderInfo orderInfo = orderInfoResult.getData();
				if (SystemConstant.ORDER_STATUS_CANCEL.equals(orderInfo.getOrderStatus())) {
					throw new GuiguException(ResultCodeEnum.ORDER_CANCEL);
				}

				// 保存交易信息
				paymentInfoService.savePaymentInfo(orderInfo, paymentType);

				description = orderInfo.getOrderTitle();
			}else {			// 充值支付的逻辑

			log.info("充值支付，请求微信支付平台支付下单接口...");

			// 根据订单的编号查询充值订单的数据
			Result<RechargeInfo> rechargeInfoResult = rechargeInfoFeignClient.getRechargeInfo(orderNo);
			RechargeInfo rechargeInfo = rechargeInfoResult.getData();

			// 保存交易信息
			paymentInfoService.savePaymentInfo(rechargeInfo,paymentType);

			description = "账户充值" ;
		}

			// 和微信支付平台进行对接 ，请求jsapi的下单接口
			JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

			// 创建PrepayRequest对象，封装预下单的请求参数
			PrepayRequest prepayRequest = new PrepayRequest();

			// 付款金额
			Amount amount = new Amount();
			// 单位就是分
			amount.setTotal(1);
			prepayRequest.setAmount(amount);
			prepayRequest.setAppid(wxPayV3Config.getAppid());
			prepayRequest.setMchid(wxPayV3Config.getMerchantId());
			prepayRequest.setDescription(description);
			prepayRequest.setNotifyUrl(wxPayV3Config.getNotifyUrl());
			prepayRequest.setOutTradeNo(orderNo);

			// 获取当前登录的用户的id
			Long userId = AuthContextHolder.getUserId();
			Result<UserInfo> userInfoResult = userInfoFeignClient.findUserInfoByUserId(userId);
			UserInfo userInfo = userInfoResult.getData();
			Payer payer = new Payer();
			payer.setOpenid(userInfo.getWxOpenId());
			prepayRequest.setPayer(payer);

			// response包含了调起支付所需的所有参数，可直接用于前端调起支付
			PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(prepayRequest);

			// 解析响应结果，构建响应数据
			WeChatPayVo weChatPayVo = new WeChatPayVo();
			weChatPayVo.setTimeStamp(response.getTimeStamp());
			weChatPayVo.setNonceStr(response.getNonceStr());
			weChatPayVo.setPackageVal(response.getPackageVal());
			weChatPayVo.setSignType(response.getSignType());
			weChatPayVo.setPaySign(response.getPaySign());

			// 返回响应数据
			return weChatPayVo;
		} catch (GuiguException e) {
			throw new GuiguException(501,"createJsapi,微信下单错误");
		}

	}
	/**
	 * @description: 根据订单号 查询支付状态查询
	 * @author Petrichor
	 * @date 2024/1/10 19:50
	 * @param orderNo 订单号
	 * @return 支付状态查询
	 **/
	@Override
	public boolean queryPayStatus(String orderNo) {

		try {

			// 和微信支付平台进行对接 ，请求jsapi的下单接口
			JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

			// 创建QueryOrderByOutTradeNoRequest对象
			QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new QueryOrderByOutTradeNoRequest() ;
			queryOrderByOutTradeNoRequest.setOutTradeNo(orderNo);
			queryOrderByOutTradeNoRequest.setMchid(wxPayV3Config.getMerchantId());

			// 响应结果对象 // 发送查询请求
			Transaction transaction = service.queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest);

			// 解析响应结果
			if(transaction != null) {

				Transaction.TradeStateEnum tradeState = transaction.getTradeState();
				if(tradeState == Transaction.TradeStateEnum.SUCCESS) {
					// 支付成功了
					paymentInfoService.updatePaymentStatus(transaction) ; 	//  更新交易信息的支付状态
					return true ;
				}

			}else {

				return false ;
			}

		}catch (Exception e) {
			e.printStackTrace();
			return false ;
		}

		return false;

	}
	/**
	 * @description: 微信支付异步通知接口
	 * @author Petrichor
	 * @date 2024/1/10 20:56
	 **/
	@Override
	public void wxnotify(HttpServletRequest request) {
		// 获取请求参数
		String wechatPaySerial = request.getHeader("Wechatpay-Serial");
		String nonce = request.getHeader("Wechatpay-Nonce");
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		String signature = request.getHeader("Wechatpay-Signature");

		// HTTP请求体 body。切记使用原始报文，不要用JSON对象序列化后的字符串，避免验签的body和原文不一致。
		String requestBody = PayUtil.readData(request);

		// 构造 RequestParam
		RequestParam requestParam = new RequestParam.Builder()
				.serialNumber(wechatPaySerial)
				.nonce(nonce)
				.signature(signature)
				.timestamp(timestamp)
				.body(requestBody)
				.build();

		// 初始化 NotificationParser
		NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);

		// 解析请求参数得到Transaction对象
		Transaction result = parser.parse(requestParam, Transaction.class);

		// 更新支付信息数据的支付状态
		if(result != null && result.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
			paymentInfoService.updatePaymentStatus(result);
		}

	}
}
